home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Misc Servers / Zope.exe / PROPERTY.PY < prev    next >
Encoding:
Python Source  |  2000-06-20  |  15.1 KB  |  414 lines

  1. ##############################################################################
  2. # Zope Public License (ZPL) Version 1.0
  3. # -------------------------------------
  4. # Copyright (c) Digital Creations.  All rights reserved.
  5. # This license has been certified as Open Source(tm).
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are
  8. # met:
  9. # 1. Redistributions in source code must retain the above copyright
  10. #    notice, this list of conditions, and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. #    notice, this list of conditions, and the following disclaimer in
  13. #    the documentation and/or other materials provided with the
  14. #    distribution.
  15. # 3. Digital Creations requests that attribution be given to Zope
  16. #    in any manner possible. Zope includes a "Powered by Zope"
  17. #    button that is installed by default. While it is not a license
  18. #    violation to remove this button, it is requested that the
  19. #    attribution remain. A significant investment has been put
  20. #    into Zope, and this effort will continue if the Zope community
  21. #    continues to grow. This is one way to assure that growth.
  22. # 4. All advertising materials and documentation mentioning
  23. #    features derived from or use of this software must display
  24. #    the following acknowledgement:
  25. #      "This product includes software developed by Digital Creations
  26. #      for use in the Z Object Publishing Environment
  27. #      (http://www.zope.org/)."
  28. #    In the event that the product being advertised includes an
  29. #    intact Zope distribution (with copyright and license included)
  30. #    then this clause is waived.
  31. # 5. Names associated with Zope or Digital Creations must not be used to
  32. #    endorse or promote products derived from this software without
  33. #    prior written permission from Digital Creations.
  34. # 6. Modified redistributions of any form whatsoever must retain
  35. #    the following acknowledgment:
  36. #      "This product includes software developed by Digital Creations
  37. #      for use in the Z Object Publishing Environment
  38. #      (http://www.zope.org/)."
  39. #    Intact (re-)distributions of any official Zope release do not
  40. #    require an external acknowledgement.
  41. # 7. Modifications are encouraged but must be packaged separately as
  42. #    patches to official Zope releases.  Distributions that do not
  43. #    clearly separate the patches from the original work must be clearly
  44. #    labeled as unofficial distributions.  Modifications which do not
  45. #    carry the name Zope may be packaged in any form, as long as they
  46. #    conform to all of the clauses above.
  47. # Disclaimer
  48. #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
  49. #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  51. #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
  52. #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  54. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  55. #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  56. #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  57. #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  58. #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. #   SUCH DAMAGE.
  60. # This software consists of contributions made by Digital Creations and
  61. # many individuals on behalf of Digital Creations.  Specific
  62. # attributions are listed in the accompanying credits file.
  63. ##############################################################################
  64. """Provide management of common instance property sheets
  65. """
  66.  
  67. import OFS.PropertySheets, Globals, OFS.SimpleItem, OFS.PropertyManager
  68. import Acquisition
  69. from string import join, upper
  70. from AccessControl.Permission import pname
  71.  
  72. class ClassCaretaker:
  73.     def __init__(self, klass): self.__dict__['_k']=klass
  74.     def __getattr__(self, name): return getattr(self._k, name)
  75.     def __setattr__(self, name, v):
  76.         klass=self._k
  77.         setattr(klass, name, v)
  78.         if not getattr(klass,'_p_changed',None):
  79.             get_transaction().register(klass)
  80.             klass._p_changed=1        
  81.     def __delattr__(self, name):
  82.         klass=self._k
  83.         delattr(klass, name)
  84.         if not getattr(klass,'_p_changed',None):
  85.             get_transaction().register(klass)
  86.             klass._p_changed=1 
  87.  
  88.  
  89. class ZCommonSheet(OFS.PropertySheets.PropertySheet, OFS.SimpleItem.Item):
  90.     "Property Sheet that has properties common to all instances"
  91.     meta_type="Common Instance Property Sheet"
  92.     _properties=()
  93.  
  94.     manage_options=(
  95.         {'label':'Properties', 'action':'manage',
  96.          'help':('OFSP','Properties.stx')},
  97.         {'label':'Define Permissions', 'action':'manage_security',
  98.          'help':('OFSP','Security_Define-Permissions.stx')},
  99.         )
  100.  
  101.     __ac_permissions__=(
  102.         ('Manage Z Classes', ('', 'manage')),
  103.         )
  104.     
  105.     def __init__(self, id, title):
  106.         self.id=id
  107.         self.title=title
  108.         self._md={}
  109.  
  110.     def manage_afterAdd(self,item,container):
  111.         if item is not self: return
  112.         if self._properties:
  113.             raise ValueError, (
  114.                 'Non-empty propertysheets cannot currently be '
  115.                 'added (or copied).<p>')
  116.  
  117.     def v_self(self):
  118.         klass=self.aq_inner.aq_parent.aq_parent.aq_parent._zclass_
  119.         return ClassCaretaker(klass)
  120.  
  121.     def p_self(self): return self
  122.  
  123.     def _view_widget_for_type(self, t, id):
  124.         if t not in ('lines', 'tokens'):
  125.             return '<dtml-var %s>' % id
  126.         return """
  127.         <dtml-in %s>
  128.            <dtml-var sequence-item>
  129.         </dtml-in %s>
  130.         """ % (id, id)
  131.  
  132.     def manage_createView(self, id, title='', ps_view_type=None, REQUEST=None):
  133.         """Create a view of a property sheet
  134.         """
  135.         if ps_view_type == 'Edit':
  136.             return self.manage_createEditor(id, title, REQUEST)
  137.             
  138.         r=['<dtml-var standard_html_header>',
  139.            '<table>']
  140.         a=r.append
  141.         for p in self.propertyMap():
  142.             pid=p['id']
  143.             pid=upper(pid[:1])+pid[1:]
  144.             a('  <tr><th align=left valign=top>%s</th>' % pid)
  145.             a('      <td align=left valign=top>%s</td>' %
  146.               self._view_widget_for_type(p['type'], p['id'])
  147.               )
  148.             a('  </tr>')
  149.         a('</table>')
  150.         a('<dtml-var standard_html_footer>')
  151.         r=join(r,'\n')
  152.         self.aq_parent.aq_parent.methods.manage_addDTMLMethod(id, title, r)
  153.         if REQUEST is not None:
  154.             REQUEST['RESPONSE'].redirect(REQUEST['URL3']+'/methods/manage')
  155.  
  156.     def _edit_widget_for_type(self, t, id, p):
  157.         if t in ('int', 'long', 'float', 'date', 'string'):
  158.             if t=='string': q=' html_quote'
  159.             else: q=''
  160.             return ('''
  161.             <input name="%s:%s" size="35"
  162.                    value="<dtml-var %s%s>">'''
  163.                     % (id, t, id, q)
  164.                     )
  165.         if t=='boolean':
  166.             return ('''
  167.             <input type="checkbox" name="%s:boolean" size="35"
  168.                 <dtml-if %s>CHECKED</dtml-if>>'''
  169.                     % (id, id)
  170.                     )
  171.                     
  172.         if t=='tokens':
  173.             return ('''
  174.             <input type="text" name="%s:tokens" size="35"
  175.                value="<dtml-in %s><dtml-var sequence-item> </dtml-in>">'''
  176.                     % (id, id)
  177.                     )
  178.                     
  179.         if t=='text':
  180.             return ('''
  181.             <textarea name="%s:text" rows="6" cols="35"><dtml-var %s
  182.             ></textarea>'''
  183.                     % (id, id)
  184.                     )
  185.                     
  186.         if t=='lines':
  187.             return ('''
  188.             <textarea name="%s:lines" rows="6" cols="35"><dtml-in %s
  189.             ><dtml-var sequence-item>\n</dtml-in></textarea>'''
  190.                     % (id, id) 
  191.                     )
  192.  
  193.                     
  194.         if t=='selection':
  195.             return ('''
  196.             <dtml-if "_.has_key('%(id)s')">
  197.             <select name="%(id)s">
  198.               <dtml-in "_.string.split('%(select_variable)s')">
  199.                 <option
  200.                   <dtml-if "_['sequence-item']=='%(id)s'">
  201.                   SELECTED</dtml-if>
  202.                   ><dtml-var sequence-item></option>
  203.               </dtml-in>
  204.             </select>
  205.             <dtml-else>
  206.               No value for %(id)s
  207.             </dtml-if>'''            
  208.                     % p
  209.                     )
  210.  
  211.         return ''
  212.  
  213.     def manage_beforeDelete(self, item, container):
  214.         if self is item:
  215.             for d in self._properties:
  216.                 self.delClassAttr(d['id'])
  217.  
  218.     def manage_createEditor(self, id, title='', REQUEST=None):
  219.         """Create an edit interface for a property sheet
  220.         """
  221.         r=['<html><head><title><dtml-var title_or_id></title></head>',
  222.            '<body bgcolor="#FFFFFF" link="#000099" vlink="#555555">',
  223.            '<dtml-var manage_tabs>',
  224.            '<form action="propertysheets/%s/manage_editProperties"><table>'
  225.            % self.id]
  226.         a=r.append
  227.         for p in self.propertyMap():
  228.             a('  <tr><th align=left valign=top>%s</th>' % p['id'])
  229.             a('      <td align=left valign=top>%s</td>' %
  230.               self._edit_widget_for_type(p['type'], p['id'], p)
  231.               )
  232.             a('  </tr>')
  233.         a('  <tr><td colspan=2>')
  234.         a('    <input type=submit value=" Change ">')
  235.         a('    <input type=reset value=" Reset ">')
  236.         a('  </td></tr>')
  237.         a('</table></form>')
  238.         a('</body></html>')
  239.         r=join(r,'\n')
  240.         self.aq_parent.aq_parent.methods.manage_addDTMLMethod(id, title, r)
  241.         if REQUEST is not None:
  242.             REQUEST['RESPONSE'].redirect(REQUEST['URL3']+'/methods/manage')
  243.  
  244.     def permissionMappingPossibleValues(self):
  245.         return self.classDefinedAndInheritedPermissions()
  246.  
  247.     manage_security=Globals.HTMLFile('AccessControl/methodAccess')
  248.     def manage_getPermissionMapping(self):
  249.         ips=self.getClassAttr('propertysheets')
  250.         ips=getattr(ips, self.id)
  251.         
  252.         # ugh
  253.         perms={}
  254.         for p in self.classDefinedAndInheritedPermissions():
  255.             perms[pname(p)]=p
  256.  
  257.         r=[]
  258.         for p in property_sheet_permissions:
  259.             v=getattr(ips, pname(p))
  260.             r.append(
  261.                 {'permission_name': p,
  262.                  'class_permission': perms.get(v,'')
  263.                  })
  264.  
  265.         return r
  266.     
  267.     def manage_setPermissionMapping(self, permission_names=[],
  268.                                     class_permissions=[],
  269.                                     REQUEST=None):
  270.         "Change property sheet permissions"
  271.         ips=self.getClassAttr('propertysheets')
  272.         ips=getattr(ips, self.id)
  273.  
  274.         perms=self.classDefinedAndInheritedPermissions()
  275.         for i in range(len(permission_names)):
  276.             name=permission_names[i]
  277.             p=class_permissions[i]
  278.             if p and (p not in perms):
  279.                 __traceback_info__=perms, p, i
  280.                 raise 'Invalid class permission'
  281.  
  282.             if name not in property_sheet_permissions: continue
  283.  
  284.             setattr(ips, pname(name), pname(p))
  285.  
  286.         if REQUEST is not None:
  287.             return self.manage_security(
  288.                 self, REQUEST, 
  289.                 manage_tabs_message='The permission mapping has been updated')
  290.  
  291. property_sheet_permissions=(
  292.     # 'Access contents information',
  293.     'Manage properties',
  294.     )
  295.  
  296. class ZInstanceSheet(OFS.PropertySheets.FixedSchema,
  297.                      OFS.PropertySheets.View,
  298.                     ):
  299.     "Waaa this is too hard"
  300.  
  301.     _Manage_properties_Permission='_Manage_properties_Permission'
  302.     _Access_contents_information_Permission='_View_Permission'
  303.  
  304.     __ac_permissions__=(
  305.         ('Manage properties', ('manage_addProperty',
  306.                                'manage_editProperties',
  307.                                'manage_delProperties',
  308.                                'manage_changeProperties',
  309.                                'manage',
  310.                                )),
  311.         ('Access contents information', ('hasProperty', 'propertyIds',
  312.                                          'propertyValues','propertyItems',''),
  313.          ),
  314.         )
  315.     
  316.     def v_self(self):
  317.         return self.aq_inner.aq_parent.aq_parent
  318.  
  319. Globals.default__class_init__(ZInstanceSheet)
  320.     
  321. def rclass(klass):
  322.     if not getattr(klass, '_p_changed', 0):
  323.         get_transaction().register(klass)
  324.         klass._p_changed=1
  325.  
  326. class ZInstanceSheetsSheet(OFS.Traversable.Traversable,
  327.                            OFS.PropertySheets.View,
  328.                            OFS.ObjectManager.ObjectManager):
  329.     "Manage common property sheets"
  330.  
  331.     # Note that we need to make sure we add and remove
  332.     # instance sheets.
  333.     id='common'
  334.     isPrincipiaFolderish=1
  335.     icon="p_/Propertysheets_icon"
  336.     dontAllowCopyAndPaste=1
  337.  
  338.     def tpURL(self): return 'propertysheets/common'
  339.  
  340.     def _setOb(self, id, value):
  341.         setattr(self, id, value)
  342.         pc=self.aq_inner.aq_parent.aq_parent._zclass_propertysheets_class
  343.         setattr(pc,id,ZInstanceSheet(id,value))
  344.         pc.__propset_attrs__=tuple(map(lambda o: o['id'], self._objects))
  345.         rclass(pc)
  346.         
  347.  
  348.     def _delOb(self, id):
  349.         delattr(self, id)
  350.         pc=self.aq_inner.aq_parent.aq_parent._zclass_propertysheets_class
  351.         try: delattr(pc,id)
  352.         except: pass
  353.         pc.__propset_attrs__=tuple(map(lambda o: o['id'], self._objects))
  354.         rclass(pc)
  355.  
  356.     meta_types=(
  357.         Globals.Dictionary(name=ZCommonSheet.meta_type,
  358.                            action='manage_addCommonSheetForm'),
  359.         )
  360.  
  361.     def all_meta_types(self): return self.meta_types
  362.  
  363.     manage=Globals.HTMLFile('OFS/main')
  364.     manage_addCommonSheetForm=Globals.HTMLFile('addCommonSheet', globals())
  365.  
  366.     def manage_addCommonSheet(self, id, title, REQUEST=None):
  367.         "Add a property sheet"
  368.         o=ZCommonSheet(id, title)
  369.         self._setObject(id, o)
  370.         if REQUEST is not None: return self.manage_main(self, REQUEST)
  371.  
  372. def klass_sequence(klass,attr,result=None):
  373.     if result is None: result={}
  374.     if hasattr(klass,attr):
  375.         for i in getattr(klass,attr): result[i]=1
  376.         for klass in klass.__bases__:
  377.             klass_sequence(klass, attr, result)
  378.     return result
  379.  
  380. class ZInstanceSheets(OFS.PropertySheets.PropertySheets, Globals.Persistent):
  381.     " "
  382.     __propset_attrs__=()    
  383.     _implements_the_notional_subclassable_propertysheet_class_interface=1
  384.  
  385.     def __propsets__(self):
  386.         propsets=ZInstanceSheets.inheritedAttribute('__propsets__')(self)
  387.         r=[]
  388.         for id in klass_sequence(self.__class__,'__propset_attrs__').keys():
  389.             r.append(getattr(self, id))
  390.         return propsets+tuple(r)
  391.  
  392.   
  393.